package com.xframe.xdal.core.util.pdf;

import com.itextpdf.text.*;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.io.FileUtils;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.plot.DefaultDrawingSupplier;
import org.jfree.chart.plot.PieLabelLinkStyle;
import org.jfree.chart.renderer.category.StandardBarPainter;
import org.jfree.chart.renderer.xy.StandardXYBarPainter;
import org.jfree.chart.ui.RectangleInsets;
import java.awt.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Collection;

@Log4j2
public class PdfBuilder {

    public static int ALIGN_LEFT = 0;
    public static int ALIGN_CENTER = 1;
    public static int ALIGN_RIGHT = 2;
    public static int ALIGN_JUSTIFIED = 3;
    public static int ALIGN_TOP = 4;
    public static int ALIGN_MIDDLE = 5;
    public static int ALIGN_BOTTOM = 6;
    public static int ALIGN_BASELINE = 7;
    public static int ALIGN_JUSTIFIED_ALL = 8;



    /**
     * 文档作者
     */
    private String author;
    /**
     * 文档创建者
     */
    private String creator;
    /**
     * 文档保存路径
     */
    private String path;

    /**
     * 当前的文档内容
     */
    private Document document;
    /**
     * 当前的文档大小
     */
    private Rectangle pageSize;

    public Rectangle getPageSize(){
        return this.pageSize;
    }

    public Document getDocument(){
        return this.document;
    }

    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    private PdfWriter writer;
    /**
     * 私有构造函数
     *
     * @param author 作者
     * @param creator 创建者
     * @param path 文档保存路径
     */
    private PdfBuilder(String author,String creator,String path){
        this.author = author;
        this.creator = creator;
        this.path = path;
        // Rectangle A4 = new RectangleReadOnly(595.0F, 842.0F); A4
        //new RectangleReadOnly(842.0F, 1191.0F); A3
        // RectangleReadOnly(1191.0F, 1684.0F); A2
        // RectangleReadOnly(1684.0F, 2384.0F); A1
        // new RectangleReadOnly(2384.0F, 3370.0F); A0
        this.pageSize = PageSize.A3;

        //this.pageSize.getWidth();
    }
    private static final java.awt.Font FONT = new java.awt.Font("STSongStd-Light",
            java.awt.Font.BOLD, 12);
    public static Color[] CHART_COLORS = {
            new Color(146, 29, 34),
            new Color(126, 126, 126),
            new Color(31, 129, 188),
            new Color(92, 92, 97),
            new Color(144, 237, 125),
            new Color(255, 188, 117),
            new Color(153, 158, 255),
            new Color(255, 117, 153),
            new Color(253, 236, 109),
            new Color(128, 133, 232),
            new Color(158, 90, 102),
            new Color(255, 204, 102)};
    static {
        setChartTheme();
    }
    /**
     * 中文主题样式 解决乱码
     */
    public static void setChartTheme() {
        // 设置中文主题样式 解决乱码
        StandardChartTheme chartTheme = new StandardChartTheme("CN");
        // 设置标题字体
        chartTheme.setExtraLargeFont(FONT);
        // 设置图例的字体
        chartTheme.setRegularFont(FONT);
        // 设置轴向的字体
        chartTheme.setLargeFont(FONT);
        chartTheme.setSmallFont(FONT);
        chartTheme.setTitlePaint(new Color(51, 51, 51));
        chartTheme.setSubtitlePaint(new Color(85, 85, 85));
        // 设置标注
        chartTheme.setLegendBackgroundPaint(Color.WHITE);
        chartTheme.setLegendItemPaint(Color.BLACK);
        chartTheme.setChartBackgroundPaint(Color.WHITE);
        // 绘制颜色绘制颜色.轮廓供应商
        // paintSequence,outlinePaintSequence,strokeSequence,outlineStrokeSequence,shapeSequence

        Paint[] OUTLINE_PAINT_SEQUENCE = new Paint[]{Color.WHITE};
        // 绘制器颜色源
        DefaultDrawingSupplier drawingSupplier = new DefaultDrawingSupplier(CHART_COLORS, CHART_COLORS, OUTLINE_PAINT_SEQUENCE,
                DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE, DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE,
                DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE);
        chartTheme.setDrawingSupplier(drawingSupplier);
        // 绘制区域
        chartTheme.setPlotBackgroundPaint(Color.WHITE);
        // 绘制区域外边框
        chartTheme.setPlotOutlinePaint(Color.WHITE);
        // 链接标签颜色
        chartTheme.setLabelLinkPaint(new Color(8, 55, 114));
        chartTheme.setLabelLinkStyle(PieLabelLinkStyle.CUBIC_CURVE);

        chartTheme.setAxisOffset(new RectangleInsets(5, 12, 5, 12));
        // X坐标轴垂直网格颜色
        chartTheme.setDomainGridlinePaint(new Color(192, 208, 224));
        // Y坐标轴水平网格颜色
        chartTheme.setRangeGridlinePaint(new Color(192, 192, 192));

        chartTheme.setBaselinePaint(Color.WHITE);
        chartTheme.setCrosshairPaint(Color.BLUE);
        // 坐标轴标题文字颜色
        chartTheme.setAxisLabelPaint(new Color(51, 51, 51));
        // 刻度数字
        chartTheme.setTickLabelPaint(new Color(67, 67, 72));
        // 设置柱状图渲染
        chartTheme.setBarPainter(new StandardBarPainter());
        // XYBar 渲染
        chartTheme.setXYBarPainter(new StandardXYBarPainter());

        chartTheme.setItemLabelPaint(Color.black);
        chartTheme.setThermometerPaint(Color.white);

        ChartFactory.setChartTheme(chartTheme);
    }

    /**
     * 设置图片
     *
     * @param author 作者
     * @param creator 创建者
     * @param path 文档保存路径
     *
     * @return PdfBuilder
     */
    public static PdfBuilder create(String author,String creator,String path){
        PdfBuilder pdfBuilder = new PdfBuilder(author,creator,path);
        return pdfBuilder;
    }

    /**
     * 设置图片
     * @return this
     */
    public PdfBuilder init() throws DocumentException, IOException {
        // 创建一个文档（默认大小A4，边距36, 36, 36, 36）
        document = new Document();


        // 设置文档大小
        document.setPageSize(pageSize);
        // 设置边距，单位都是像素，换算大约1厘米=28.33像素
        //document.setMargins(50, 50, 50, 50);
        document.setMargins(10, 10, 0, 0);
        // 创建writer，通过writer将文档写入磁盘
        writer = PdfWriter.getInstance(document, outputStream);
        // 打开文档，只有打开后才能往里面加东西
        document.open();

        // 设置作者
        document.addAuthor(author);
        // 设置创建者
        document.addCreator(creator);
        return this;
    }


    /**
     * 设置图片
     *
     * @param imgPath 图片路径
     * @param alignment 对齐方式
     * @param width 图片宽度
     * @param height 图片高度
     * @return this
     */
    public PdfBuilder setImage(String imgPath,int alignment,int width,int height) throws DocumentException, IOException {
        Image image = Image.getInstance(imgPath);
        image.setAlignment(alignment);
        image.scaleAbsolute(width, height);
        image.setSpacingBefore(10);
        image.setSpacingAfter(10);
        document.add(image);
        return this;
    }
    /**
     * 设置图片
     *
     * @param imgPath 图片路径
     * @param width 图片宽度
     * @param height 图片高度
     * @return this
     */
    public PdfBuilder setImage(String imgPath,int width,int height) throws DocumentException, IOException {
        return setImage(imgPath,Image.ALIGN_CENTER,width,height);
    }
    /**
     * 设置图片
     *
     * @param imgPath 图片路径
     * @return this
     */
    public PdfBuilder setImage(String imgPath) throws DocumentException, IOException {
        return setImage(imgPath,Image.ALIGN_CENTER,(int)this.pageSize.getWidth() - 2,500);
    }


    /**
     * 根据传入的参数生成PDF文档使用的字体
     *
     * @param fontSize  字体大小
     * @param fontMode  字体正常、加粗、下划线等
     * @param fontColor 字体颜色
     * @return 返回生成的字体
     */
    private static Font createFont(int fontSize, int fontMode, BaseColor fontColor) throws DocumentException, IOException {
        // 微软雅黑
        BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        return new Font(bfChinese, fontSize, fontMode, fontColor);
    }

    /**
     * 设置文本
     *
     * @param title 文本
     * @param style 文本风格
     * @param align 对齐方式
     * @param fontSize 字体大小
     * @param color 字体颜色
     * @return this
     */
    public PdfBuilder setHead(String title,int style,int align, int fontSize,BaseColor color) throws DocumentException, IOException {
        return setText(title,style,align,fontSize,color);
    }
    public PdfBuilder setHead(String title) throws DocumentException, IOException {
        return setHead(title,FontStyle.NORMAL,ALIGN_CENTER,24,BaseColor.BLACK);
    }
    /**
     * 设置文本标题
     *
     * @param title 文本
     * @param style 文本风格
     * @return this
     */
    public PdfBuilder setHead(String title,int style) throws DocumentException, IOException {
        return setHead(title,style,ALIGN_CENTER,24,BaseColor.BLACK);
    }
    /**
     * 设置文本标题
     *
     * @param title 文本
     * @param style 文本风格
     * @param align 对齐方式
     * @return this
     */
    public PdfBuilder setHead(String title,int style,int align) throws DocumentException, IOException {
        return setHead(title,style,align,24,BaseColor.BLACK);
    }
    /**
     * 设置文本标题
     *
     * @param title 文本
     * @param style 文本风格
     * @param align 对齐方式
     * @param fontSize 字体大小
     * @return this
     */
    public PdfBuilder setHead(String title,int style,int align,int fontSize) throws DocumentException, IOException {
        return setHead(title,style,align,fontSize,BaseColor.BLACK);
    }

    /**
     * 设置文本
     *
     * @param text 文本
     * @param style 文本风格
     * @param alignment 对齐方式
     * @param fontSize 字体大小
     * @param color 字体颜色
     * @param beforeSpacing 段落前间距
     * @param afterSpacing 段落后间距
     * @return this
     */
    public PdfBuilder setText(String text, int style, int alignment,
                              int fontSize,BaseColor color,float beforeSpacing,float afterSpacing) throws DocumentException, IOException {

        Font font = createFont(fontSize, style, color);
        Paragraph paragraph = new Paragraph(text, font);
        paragraph.setAlignment(alignment);
        //设置段落前后间距
        paragraph.setSpacingBefore(beforeSpacing);
        paragraph.setSpacingAfter(afterSpacing);
        document.add(paragraph);
        return this;
    }

    /**
     * 设置文本
     *
     * @param text 文本
     * @param style 文本风格
     * @param alignment 对齐方式
     * @param fontSize 字体大小
     * @param color 字体颜色
     * @return this
     */
    public PdfBuilder setText(String text, int style, int alignment,
                              int fontSize,BaseColor color) throws DocumentException, IOException {


        //String str = color.toString();
        Font font = createFont(fontSize, style, color);
        Paragraph paragraph = new Paragraph(text, font);
        paragraph.setAlignment(alignment);
        //设置段落前后间距
        paragraph.setSpacingBefore(10);
        paragraph.setSpacingAfter(10);

        document.add(paragraph);
        return this;
    }



    /**
     * 表格
     *
     * @param tableColList 表头
     * @param values 数据
     * @throws DocumentException
     * @throws IOException
     */
    public PdfBuilder setTable(java.util.List<TableCol> tableColList,
                               Collection values) throws DocumentException, IOException {

        PdfTableOpt pdfTableOpt = new PdfTableOpt(this,tableColList,values,false);
        return setTable(pdfTableOpt);
    }
    /**
     * 新的一页
     */
    public PdfBuilder setNewPage(){
        document.newPage();
        return this;
    }
    /**
     * 表格
     *
     * @param pdfTableOpt 表格设定对象
     * @throws DocumentException
     * @throws IOException
     */
    public PdfBuilder setTable(PdfTableOpt pdfTableOpt) throws DocumentException, IOException {
        pdfTableOpt.buildTabel();
        return this;
    }

    /**
     * 生成折线图
     *
     * @param title 数据
     * @param xLabel X轴
     * @param yLabel Y轴
     * @param values 数据
     * @return this
     */
    public PdfBuilder setLineChart(String title,
                                   String xLabel, String yLabel, Collection values,String groupName
            ,String keyName,String valueName) throws DocumentException, IOException {


        LineChartOpt lineChartOpt = LineChartOpt.buildLineChartOpt(this,title,xLabel,yLabel,values,groupName,keyName,valueName);
        lineChartOpt.buildLineChart();
        return this;
    }

    /**
     * 生成堆叠柱状图
     *
     * @param title 数据
     * @param xLabel X轴
     * @param yLabel Y轴
     * @param values 数据
     * @return this
     */
    public PdfBuilder setBarChart(String title,
                                  String xLabel, String yLabel, Collection values,String groupName
            ,String keyName,String valueName) throws DocumentException, IOException {


        BarChartOpt barChartOpt = BarChartOpt.buildBarChartOpt(this,false,title,xLabel,yLabel,values,groupName,keyName,valueName);
        barChartOpt.buildBarChart();
        return this;
    }

    public PdfBuilder setStackedBarChart(String title,
                                         String xLabel, String yLabel, Collection values,String groupName
            ,String keyName,String valueName) throws DocumentException, IOException {
        BarChartOpt barChartOpt = BarChartOpt.buildBarChartOpt(this,true,title,xLabel,yLabel,values,groupName,keyName,valueName);
        barChartOpt.buildBarChart();
        return this;

    }

    /**
     * 生成堆叠柱状图
     *
     * @param values 数据
     * @param keyName 数据
     * @param valueName 数据
     * @return this
     */
    public PdfBuilder setPieChart(Collection values,boolean percentageFlag,String keyName,String valueName) throws DocumentException, IOException {
        PieChartOpt pieChartOpt = PieChartOpt.buildPieChartOpt(this,values,percentageFlag,keyName,valueName);
        pieChartOpt.buildPieChart();
        return this;
    }


    /**
     * 保存到路径磁盘
     */
    public void saveToPath() throws IOException, DocumentException {
        document.close();
        writer.close();
        File file = new File(this.path);
        log.info("{}",file.getAbsolutePath());
        FileUtils.copyInputStreamToFile(new ByteArrayInputStream(outputStream.toByteArray()),file);
    }
}
